package com.yixq.soa.service.web.utils;

import com.yixq.soa.service.comm.ResultCode;
import com.yixq.soa.service.comm.ResultData;
import com.yixq.soa.service.comm.vo.PageVo;
import com.yixq.soa.service.web.auth.TokenManager;
import com.yixq.soa.service.web.auth.UserRealm;
import com.yixq.soa.service.web.auth.model.TokenModel;
import com.yixq.soa.service.web.dto.DoorduResult;
import com.yixq.soa.service.web.service.DataValidService;
import com.github.miemiedev.mybatis.paginator.domain.PageList;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public class BaseController {
	@Autowired
	protected TokenManager tokenManager;
	protected String errorMessage="";
	public ResponseEntity<Object> ResponseJSON(Object body) {
		return ResponseJSON(body,HttpStatus.OK);
	}
	
	public ResponseEntity<Object> ResponseJSON(Object body,HttpStatus status) {
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		ResponseEntity<Object> res = new ResponseEntity<Object>(body, headers, status);
		
		//_$_beginTime
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		
		Long beginTime = (Long)request.getAttribute("_$_beginTime");
		if(beginTime != null && beginTime > 0){
			HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
					.getResponse();
			
			Long maxTime = (Long)request.getAttribute("_$_use_time_max");
			
			Long endTime = System.currentTimeMillis();
			Long userTime = endTime - beginTime;
			response.addHeader("time-used", userTime+"ms");
			
			if(maxTime < userTime){
				//log warn
			}
			
		}
		

		return res;
	}

	/**
	 * 
	 * @Title: result
	 * @Description 正确返回调用此方法
	 * @param t
	 *            DoorduResult 的子类
	 * @return 如果DoorduResult的参数没有指定,则自动赋值为操作成功的值.
	 */
	private <T extends DoorduResult<?>> ResponseEntity<Object> result(T t) {
		DoorduResult<?> r = (DoorduResult<?>) t;

		if (r.getSuccess() == null) {//没有指定则设置为 true
			r.setSuccess(true);
		}
		return ResponseJSON(t);
	}
	

	/**
	 * 返回错误结果.
	* @Title: error 
	* @Description
	* @param t
	* @return
	 */
	public <T extends DoorduResult<?>> ResponseEntity<Object> error(T t){
		if(t != null){
			DoorduResult<?> r = (DoorduResult<?>) t;
			if(r.getSuccess() == null){
				r.setSuccess(false);
			}
		}

		return ResponseJSON(t);
	}

	/**
	 * 返回正确的响应(200状态码)<br>
	 * <p>如果传递的参数为分页对象 {@code PageList}, 则使用分页数据中的总记录数</p>
	 * <p>如果传递的参数为结果对象 {@code DoorduResult}, 则完全使用该对象的属性进行输出.</p>
	 * <p>其他对象则使用默认封装后输出.</p>
	 * @param result 可以为 null,PageList,DoorduResult 3种对象.其他对象将使用默认输出.
	 * @return 封装好的返回对象 {@code ResponseEntity}
	 */
	public ResponseEntity<Object> ok(Object result) {
		if(result == null){
			return ok(new Object(),"");
		}
		if(result instanceof PageList){
			PageList<?> pagelist = (PageList<?>)result;
			Long dc = 0L;
		
			if (pagelist.getPaginator()!= null) {//没有设置记录数则自动设置
				dc = Long.valueOf(pagelist.getPaginator().getTotalCount());
			}
			return ok(pagelist,dc);
		}
		if(result instanceof DoorduResult){
			DoorduResult<?> dresult = (DoorduResult<?>)result;
			return result(dresult);
		}
		return ok(result,"");
		
	}

	/**
	 * 正常接口返回,推荐使用 {@code ok(DoorduResult<?> result) }  方法
	 * @see
	 * @param data
	 * @param message
	 * @return
	 */
	public ResponseEntity<Object> ok(Object data, String message) {
		return ok(ResultCode.RESPONSE_SUCCESS, message, "", data, 0L);
	}
	
	/**
	 * 解析ResultData返回结果
	 * @param result
	 * @return
	 */
	public ResponseEntity<Object> result(ResultData<?> result) {
		Map<String, Object> resultData = new HashMap<>();
		
		String msg = null;
		String desc = null;
		String code = null;
		
		if (result == null) {
			code = ResultCode.RESPONSE_UNKNOWN_ERROR;
			desc = msg = ResultCode.errmap.get(code);
			resultData.put("code", ResultCode.RESPONSE_UNKNOWN_ERROR);
			resultData.put("data", null);
			resultData.put("message", msg);
			resultData.put("desc", desc);
		} else {
			code = result.getCode();
			msg = result.getMsg();
			desc = result.getDesc();
			resultData.put("code", code);
			resultData.put("data", result.getData());
			resultData.put("message", msg);
			resultData.put("desc", desc);
		}
		
		return ResponseJSON(resultData);
	}
	
	/**
	 * 正常接口返回,推荐使用 {@code ok(DoorduResult<?> result) }  方法
	 * @see
	 * @param data
	 * @param totalCount 
	 * @return
	 */
	public ResponseEntity<Object> ok(Object data,Long totalCount) {
		return ok(ResultCode.RESPONSE_SUCCESS, "", "", data, totalCount);
	}

	/**
	 * 正常接口返回,推荐使用
	 * @param code
	 * @param msg
	 * @param desc
	 * @param data
	 * @param totalCount
	 * @return
	 */
	public ResponseEntity<Object> ok(String code, String msg,String desc, Object data, Long totalCount) {
		Map<String, Object> resultData = new HashMap<>();
		resultData.put("code", code);
		resultData.put("message", msg);
		resultData.put("data", new Object());//默认空
		resultData.put("desc", desc);
		if (totalCount != null && totalCount > 0) {
			resultData.put("totalCount", totalCount);
		}
		if(data!=null){
			if(data instanceof PageVo){
				PageVo pageVo = (PageVo)data;
				if (pageVo != null) {
					resultData.put("data", data==null ? new Object(): pageVo.getContent());
					resultData.put("totalCount", pageVo.getTotalCount());
				}
			}else if(data instanceof PageList){
				PageList<?> pagelist = (PageList<?>)data;
				if (pagelist.getPaginator() != null) {
					resultData.put("data", data==null ? new Object():data);
					resultData.put("totalCount", pagelist.getPaginator().getTotalCount());
				}
			}else if(data instanceof List){
				List<?> list = (List<?>)data;
				if(list!=null){
					resultData.put("data", data==null ? new Object():data);
					resultData.put("totalCount", list.size());
				}
			}else{
				resultData.put("data", data);
			}
		}
		//TODO Map对象的属性不能自动转换null 为 ""
		
		return ResponseJSON(resultData);
	}

	/***
	 * 返回业务异常
	 * 默认code="400"
	 * @param msg
	 * @return
	 */
	public ResponseEntity<Object> error(String msg) {
		return error(ResultCode.RESPONSE_ERROR,msg);
	}
	/***
	 * 
	 * @param msg
	 * @param code
	 * @return
	 */
	public ResponseEntity<Object> error(String code,String msg) {
		return error(code,msg,null);
	}
	/***
	 * @Title: error
	 * @Description: 
	 * @author Jason.Rao raoys@doordu.com 
	 * @date 2017年4月20日 上午6:38:22
	 * @param code  错误编码
	 * @param msg	错误信息
	 * @param desc  错误描述
	 * @return    
	 * @return ResponseEntity<Object>
	 */
	public ResponseEntity<Object> error(String code,String msg, String desc) {
		Map<String, Object> data = new HashMap<>();
		data.put("code", code);
		data.put("message", msg);
		data.put("desc", desc);
		return ResponseJSON(data);
	}

	public ResponseEntity<Object> defaultError(String desc) {
		return error(ResultCode.RESPONSE_INTRANET_ERROR, ResultCode.errmap.get(ResultCode.RESPONSE_INTRANET_ERROR), desc);
	}

	/**
	 * 校验参数错误
	 * @param desc
	 * @return
	 */
	public ResponseEntity<Object> checkParamError(String desc) {
		return error(ResultCode.ERROR_DATA_PARAM, ResultCode.errmap.get(ResultCode.ERROR_DATA_PARAM), desc);
	}
	
	public ResponseEntity<Object> dataNotMatchError() {
		return error(ResultCode.ERROR_DATA_NOT_MATCH ,ResultCode.errmap.get(ResultCode.ERROR_DATA_NOT_MATCH ),"没有符合要求的数据");
	}
	public ResponseEntity<Object> responseIntranetError() {
		return error(ResultCode.RESPONSE_INTRANET_ERROR,ResultCode.errmap.get(ResultCode.RESPONSE_INTRANET_ERROR),null);
	}
	public ResponseEntity<Object> resultDataError(ResultData<?> resultData) {
		return error(resultData.getCode(), ResultCode.errmap.get(resultData.getCode()),resultData.getDesc());
	}
	public ResponseEntity<Object> checkParamNull(String desc) {
		return error(ResultCode.ERROR_DATA_NULL,ResultCode.errmap.get(ResultCode.ERROR_DATA_NULL),desc);
	}
	
	/***
	 * 获取当前的请求信息.
	 * @return
	 */
	public HttpServletRequest getRequest() {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		
		return request;
	}
	
	/**
	 * 获取当前登录的用户信息
	 * @return
	 */
	public Optional<UserRealm>  getUserRealm(){
		HttpServletRequest request = getRequest();
		HttpSession session = request.getSession(false);
		if(session != null){
			UserRealm realm = (UserRealm)session.getAttribute(UserRealm.USER_REALM_KEY);
			return Optional.ofNullable(realm);
		}
		return Optional.empty();
	}

	/**
	 * 校验数据的合法性
	 * @param object
	 * @return
	 */
	public String checkData(Object object){
		String result = null;
		try {
			DataValidService.valid(object);
		} catch (Exception e) {
			result = "参数校验失败："+e.getMessage();
		}
		return result;
	}

	/**
	 * 校验分页参数的合法性
	 * @param pageParam
	 * @return
	 */
	public String checkPageParam(PageParam pageParam){
		String result = this.checkData(pageParam);
		if(result==null){
			if(Integer.valueOf(pageParam.getPage())<=0){
				result = "页码不能小于1";
			}
			if(Integer.valueOf(pageParam.getLimit())<=0){
				result = "每页记录数不能小于1";
			}
		}

		return result;
	}


	protected String getErrorMessage(String errorMessage){
		if(errorMessage.length()>50){
			return "系统内部异常。";
		}
		return errorMessage;
	}
	
	protected Integer getAgentId(HttpServletRequest request){
		String token=request.getHeader("token");
		if(StringUtils.isBlank(token)){
			return 0;
		}
		TokenModel tokenModel=tokenManager.getTokenModelByModel(token);
		return tokenModel==null?0:tokenModel.getAgentId();
		
	}
}
